package im.oen.boot.api.dispatch;

import im.oen.boot.api.annotation.handler.MethodAroundHandler;
import im.oen.boot.api.constant.OenApiConst;
import im.oen.boot.api.dao.AbsDao;
import im.oen.boot.api.dispatch.handler.*;
import im.oen.boot.common.constant.OenCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Kevin.Xu
 */
public class MethodHandlerExecutor {

    private Logger log = LoggerFactory.getLogger(MethodHandlerExecutor.class);

    private final String uri;
    private final AbsDao dao;
    private final Class idClass;
    private final Class entityClass;
    private final MethodAroundHandler methodAroundHandler;

    private Map<String, MethodHandler> handlers = new ConcurrentHashMap<>();

    public MethodHandlerExecutor(String uri, Class id, Class entity, MethodAroundHandler methodAroundHandler, AbsDao dao) {
        this.uri = uri;
        this.idClass = id;
        this.entityClass = entity;
        this.methodAroundHandler = methodAroundHandler;
        this.dao = dao;
        this.init();
    }

    private void init() {
        this.put(new CountMethodHandler());
        this.put(new CreateMethodHandler());
        this.put(new DeleteMethodHandler());
        this.put(new FindByIdMethodHandler());
        this.put(new FindMethodHandler());
        this.put(new UpdateMethodHandler());
        this.put(new PageMethodHandler());
    }

    private void put(MethodHandler methodHandler) {
        String cmd = methodHandler.cmd().toLowerCase();
        handlers.put(cmd, methodHandler);

        String proUri = OenApiConst.getInstance().getProjectUri();
        String apiUri = OenApiConst.getInstance().getApiUri();

        log.info("Register oen api uri : {}{}/{}/{}", proUri, apiUri, this.uri, cmd);
    }

    public Object exec(String method, String[] paths, String body) {
        MethodHandler handler = this.handlers.get(method);
        if (handler == null) {
            throw OenCode.NOT_IMPLEMENTED.exception("Method handler not found");
        }
        return handler.handler(dao, methodAroundHandler, entityClass, paths, body);
    }
}
